package cn.portx.frame.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import com.bstek.bdf3.dorado.jpa.JpaUtil;
import com.bstek.bdf3.saas.SaasUtils;
import com.bstek.bdf3.saas.command.Command;
import com.bstek.bdf3.saas.service.DataSourceService;
import com.bstek.bdf3.saas.service.EntityManagerFactoryService;
import com.bstek.bdf3.saas.service.OrganizationService;
import com.bstek.bdf3.security.ui.service.UserServiceImpl;
import com.bstek.dorado.annotation.Expose;

import cn.portx.frame.CompanyPR;
import cn.portx.frame.entity.Company;
import cn.portx.frame.entity.UserEntity;

@Service
@Transactional
public class SyncServiceImpl {

	@Autowired
	private OrganizationService organizationService;

	@Autowired
	private EntityManagerFactoryService entityManagerFactoryService;

	@Autowired
	private DataSourceService dataSourceService;

//	@Autowired
//	private DataSourceProperties properties;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private CompanyPR companyPR;

	@Autowired
	@Qualifier("ui.userService")
	private UserServiceImpl userServiceImpl;

	@Transactional
	public String syncUser(Map<String, Object> info) {
		String account = (String) info.get("account");
		String password = (String) info.get("password");
		String name = (String) info.get("name");
		String companyName = (String) info.get("companyName");
		String companyCode = "C" + (String) info.get("companyCode");
		int isAdministrator = (int) info.get("isAdministrator");

		Company c = new Company();
		c.setOrgId(companyCode);
		c.setFullName(companyName);
		c.setEnable("0");

		UserEntity user = new UserEntity();
		user.setAdministrator(isAdministrator == 1);
		user.setAccountNonExpired(true);
		user.setAccountNonLocked(true);
		user.setCredentialsNonExpired(true);
		user.setCredentialsNonExpired(true);
		user.setUsername(account);
		user.setNickname(name);
		user.setPassword(password);
		user.setOrgId(c.getOrgId());

		try {
			this.registerOrganization(c, user);
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			return "[公司（" + companyCode + "）,用户（" + account + "）]:" + e.getMessage();
		}
	}

//	@Transactional
//	public String executeSql(String sql, String companyCode) throws IOException {
//		List<Resource> resources = new ArrayList<Resource>();
//		resources.add(new ByteArrayResource(sql.getBytes()));
//		return this.runScripts(resources, companyCode);
//	}
//
//	@Transactional
//	public String executeScript(MultipartFile file, String companyCode) throws IOException {
//		List<Resource> resources = new ArrayList<Resource>();
//		resources.add(new InputStreamResource(file.getInputStream()));
//
//		return this.runScripts(resources, companyCode);
//	}
//
//	private String runScripts(List<Resource> resources, String companyCode) {
//		List<Organization> list = null;
//		if (StringUtils.isEmpty(companyCode)) {
//			//更新所有数据库
//			list = JpaUtil.linq(Organization.class).list();
//		} else {
//			//更新companyCode的数据库
//			list = JpaUtil.linq(Organization.class).idEqual(companyCode).list();
//		}
//		for (Organization org : list) {
//			entityManagerFactoryService.getOrCreateEntityManagerFactory(org);
//			DataSource ds = dataSourceService.getDataSource(org);
//			this.runScripts(resources, ds);
//		}
//		return null;
//	}

//	private void runScripts(List<Resource> resources, DataSource dataSource) {
//		ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
//		populator.setContinueOnError(this.properties.isContinueOnError());
//		populator.setSeparator(this.properties.getSeparator());
//		if (this.properties.getSqlScriptEncoding() != null) {
//			populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name());
//		}
//		for (Resource resource : resources) {
//			populator.addScript(resource);
//		}
//		DatabasePopulatorUtils.execute(populator, dataSource);
//	}

	@Transactional
	public void updatePwd(@RequestParam String timestamp, @RequestParam String sign, @RequestParam String desUsername, @RequestParam String newPwd) throws Exception {
		String username = validateSign(timestamp, desUsername, sign);
		List<UserEntity> users = JpaUtil.linq(UserEntity.class).idEqual(username).list();
		if (users.isEmpty()) {
			throw new Exception("货代系统中没有用户：" + username);
		}
		SaasUtils.doNonQuery(users.get(0).getOrgId(), new Command() {

			@Override
			public void execute() {
				userServiceImpl.changePassword(username, newPwd);
			}

		});
	}

	private void registerOrganization(Company c, UserEntity user) throws DecoderException {
		List<Company> list = JpaUtil.linq(Company.class).equal("orgId", c.getOrgId()).list();
		if (list.isEmpty()) {
			JpaUtil.persist(c);
		}
		boolean exists = JpaUtil.linq(UserEntity.class).idEqual(user.getUsername()).exists();
		if (!exists) {
			JpaUtil.persist(user);
		}
	}

	@Expose
	public void testUser() {
//		Set<String> set = new HashSet<String>();
		for (int i = 0; i < 100; i++) {
			String companyCode = "C" + i;
			String companyName = "C" + i;
			for (int j = 0; j < 60; j++) {
				String account = "user" + i + "_" + j;
				String password = "111111";
				String name = "user" + i + "_" + j;
				int isAdministrator = 1;

//				set.add(account);

				Map<String, Object> map = new HashMap<String, Object>();
				map.put("companyCode", companyCode);
				map.put("companyName", companyName);
				map.put("name", name);
				map.put("account", account);
				map.put("password", this.passwordEncoder.encode(password));
				map.put("isAdministrator", isAdministrator);

				String error = this.syncUser(map);
				if (error != null) {
					throw new RuntimeException(error);
				}
			}
		}
//		System.out.println(set.size());
	}

	@Expose
	public void testSql() {

	}

	public static void main(String[] args) throws Exception {
		encode("user1_0");
	}

	private static void encode(String username) throws Exception {
		String desKey = "4cbf0a84-7006-4e49-bcf4-5542db1f9925";
		DESKeySpec dks = new DESKeySpec(desKey.getBytes("UTF-8"));
		//实例化密钥工厂  
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		//生成密钥  
		SecretKey secretKey = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.ENCRYPT_MODE, secretKey);
		String timestamp = DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS");
		String sign = DigestUtils.md5Hex(username + timestamp + desKey).toUpperCase();
		username = Base64.encodeBase64String(cipher.doFinal(username.getBytes("UTF-8")));

		System.out.println("加密后的username=" + username);
		System.out.println("timestamp=" + timestamp);
		System.out.println("the_sign=" + sign);

		System.out.println("==========开始解密=============" + timestamp);

		validateSign(timestamp, username, sign);
	}

	private static String validateSign(String timestamp, String desUsername, String sign) throws Exception {
		String desKey = "4cbf0a84-7006-4e49-bcf4-5542db1f9925";
		DESKeySpec dks = new DESKeySpec(desKey.getBytes("UTF-8"));
		//实例化密钥工厂  
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		//生成密钥  
		SecretKey secretKey = keyFactory.generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, secretKey);
		String username = new String(cipher.doFinal(Base64.decodeBase64(desUsername)), "UTF-8");
		String the_sign = DigestUtils.md5Hex(username + timestamp + desKey).toUpperCase();

		if (StringUtils.equals(sign, the_sign)) {
			return username;
		}
		throw new Exception("签名错误！");
	}
}
